﻿using System;
using System.ComponentModel.Design;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using MyExtendProject.Common;
using MyExtendProject.DialogPages;
using Task = System.Threading.Tasks.Task;

namespace MyExtendProject.Commands
{
    /// <summary>
    /// Command handler
    /// </summary>
    internal sealed class RemoveSolotionReadonlyCommand
    {
        /// <summary>
        /// Command ID.
        /// </summary>
        public const int CommandId = 0x0100;

        /// <summary>
        /// Command menu group (command set GUID).
        /// </summary>
        public static readonly Guid CommandSet = new Guid("c25427f0-f0c1-42b2-94ff-aed239d970e1");

        /// <summary>
        /// VS Package that provides this command, not null.
        /// </summary>
        private readonly AsyncPackage package;

        /// <summary>
        /// Initializes a new instance of the <see cref="RemoveSolotionReadonlyCommand"/> class.
        /// Adds our command handlers for menu (commands must exist in the command table file)
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        /// <param name="commandService">Command service to add command to, not null.</param>
        private RemoveSolotionReadonlyCommand(AsyncPackage package, OleMenuCommandService commandService)
        {
            this.package = package ?? throw new ArgumentNullException(nameof(package));
            commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));

            var menuCommandID = new CommandID(CommandSet, CommandId);
            var menuItem = new MenuCommand(this.Execute, menuCommandID);
            commandService.AddCommand(menuItem);
        }

        /// <summary>
        /// Gets the instance of the command.
        /// </summary>
        public static RemoveSolotionReadonlyCommand Instance
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the service provider from the owner package.
        /// </summary>
        private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider
        {
            get
            {
                return this.package;
            }
        }

        /// <summary>
        /// Initializes the singleton instance of the command.
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        public static async Task InitializeAsync(AsyncPackage package)
        {
            // Verify the current thread is the UI thread - the call to AddCommand in RemoveSolotionReadonlyCommand's constructor requires
            // the UI thread.
            ThreadHelper.ThrowIfNotOnUIThread();

            OleMenuCommandService commandService = await package.GetServiceAsync((typeof(IMenuCommandService))) as OleMenuCommandService;
            Instance = new RemoveSolotionReadonlyCommand(package, commandService);
        }

        /// <summary>
        /// This function is the callback used to execute the command when the menu item is clicked.
        /// See the constructor to see how the menu item is associated with this function using
        /// OleMenuCommandService service and MenuCommand class.
        /// </summary>
        /// <param name="sender">Event sender.</param>
        /// <param name="e">Event args.</param>
        private async void Execute(object sender, EventArgs e)
        {
            var output = await CommonCommandFunction.CreatePane(package, Guid.NewGuid(), "清理解决方案只读", true, true);
            output.Activate();

            var removeSlnRdSetting = package.GetDialogPage(typeof(RemoveSolotionReadonlyCommandSettingPage)) as RemoveSolotionReadonlyCommandSettingPage;

            string slnPath = CommonCommandFunction.GetSolutionPath();
            string[] allChars = removeSlnRdSetting.SearchPattern.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            FileInfo[] allFiles = new DirectoryInfo(slnPath).GetFiles("*.*", SearchOption.AllDirectories);

            await Task.Run(() =>
            {
                try
                {
                    int count = 0;
                    foreach (var fi in allFiles.Where(file => allChars.Any(i => file.FullName.Contains(i)) && file.IsReadOnly))
                    {
                        File.SetAttributes(fi.FullName, FileAttributes.Normal);

                        output.OutputStringThreadSafe($"去只读 -> {fi.FullName}\r\n");
                        ++count;
                    }

                    //处理完成
                    output.OutputStringThreadSafe($"去只读全部完成（共计{count}个）\r\n");
                }
                catch (Exception ex)
                {
                    output.OutputStringThreadSafe("解除只读属性时出错！");
                    output.OutputStringThreadSafe("错误信息：" + ex.Message);
                }
                output.Activate();
            });
        }
    }
}
